package org.webflux.remote.client.register;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.ClassUtils;
import org.webflux.remote.client.annotation.EnableFeignWevFluxClients;
import org.webflux.remote.client.annotation.FeignWebFlux;
import org.webflux.remote.client.factoryBean.FeignWebFluxClientFactoryBean;

import java.util.Set;

public class FeignWebFluxRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware{

    private Environment environment;

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        // 1. 获取@EnableFeignWevFluxClients（扫描路径）
        String[] basePackages = (String[]) importingClassMetadata.getAnnotationAttributes(EnableFeignWevFluxClients.class.getName())
                .get("basePackages");
        if (basePackages.length == 0) {
            // 默认扫描启动类所在包
            String defaultPackage = ClassUtils.getPackageName(importingClassMetadata.getClassName());
            basePackages = new String[]{defaultPackage};
        }

        // 2. 扫描指定包下所有标注@WebFluxClient的接口
        ClassPathScanningCandidateComponentProvider scanner = this.getScanner();
        scanner.addIncludeFilter(new AnnotationTypeFilter(FeignWebFlux.class)); // 只扫描带@WebFluxClient的接口

        for (String basePackage : basePackages) {
            Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(basePackage);
            for (BeanDefinition beanDefinition : candidateComponents) {
                if (beanDefinition instanceof AnnotatedBeanDefinition) {
                    AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDefinition;
                    AnnotationMetadata metadata = annotatedBeanDefinition.getMetadata();
                    // 只处理接口
                    if (metadata.isInterface()) {
                        registerFeignClient(registry, metadata);
                    }
                }
            }
        }
    }

    protected ClassPathScanningCandidateComponentProvider getScanner() {
        return new ClassPathScanningCandidateComponentProvider(false, this.environment) {
            @Override
            protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
                boolean isCandidate = false;
                if (beanDefinition.getMetadata().isIndependent() && !beanDefinition.getMetadata().isAnnotation()) {
                    isCandidate = true;
                }

                return isCandidate;
            }
        };
    }

    // 注册Feign客户端（通过工厂Bean生成代理）
    private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata metadata) {
        String className = metadata.getClassName();

        // 构建工厂Bean的定义：FeignWebFluxClientFactoryBean
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FeignWebFluxClientFactoryBean.class);
        builder.addPropertyValue("type", className); // 接口类型

        // 注册BeanDefinition（Bean名称为接口全类名）
        registry.registerBeanDefinition(className, builder.getBeanDefinition());
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
}
